module float_mul (
	clock,
	dataa,
	datab,
	result);

	input	  clock;
	input	[31:0]  dataa;
	input	[31:0]  datab;
	output	[31:0]  result;

//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	wire dataa_exp_all_one = &dataa[30:23];
	wire dataa_exp_not_zero = |dataa[30:23];
	wire dataa_man_not_zero10 = |dataa[10:0];
	wire dataa_man_not_zero = |dataa[22:0];
	wire datab_exp_all_one = &datab[30:23];
	wire datab_exp_not_zero = |datab[30:23];
	wire datab_man_not_zero10 = |datab[10:0];
	wire datab_man_not_zero = |datab[22:0];

	wire  [47:0]   wire_man_product2_mult_result;
`ifdef isISE
mul24x24u1c   man_product2_mult( 
  .clk(clock),
  .a({1'b1, dataa[22:0]}),
  .b({1'b1, datab[22:0]}),
  .p(wire_man_product2_mult_result)
);
`endif

`ifdef isALTERA
	lpm_mult   man_product2_mult
	( 
	.aclr(0),
	.clken(1),
	.clock(clock),
	.dataa({1'b1, dataa[22:0]}),
	.datab({1'b1, datab[22:0]}),
	.result(wire_man_product2_mult_result)
	);
	defparam
		man_product2_mult.lpm_pipeline = 1,
		man_product2_mult.lpm_representation = "UNSIGNED",
		man_product2_mult.lpm_widtha = 24,
		man_product2_mult.lpm_widthb = 24,
		man_product2_mult.lpm_widthp = 48,
		man_product2_mult.lpm_widths = 1,
		man_product2_mult.lpm_type = "lpm_mult",
		man_product2_mult.lpm_hint = "DEDICATED_MULTIPLIER_CIRCUITRY=YES";
`endif

  
	reg  [8:0]   wire_exp_add_adder_result;
	reg	[0:0]	sign_node_ff0;
	reg	dataa_exp_all_one_ff_p1;
	reg	dataa_exp_not_zero_ff_p1;
	reg	dataa_man_not_zero_ff_p1;
	reg	dataa_man_not_zero_ff_p2;
	reg	datab_exp_all_one_ff_p1;
	reg	datab_exp_not_zero_ff_p1;
	reg	datab_man_not_zero_ff_p1;
	reg	datab_man_not_zero_ff_p2;
always @ (posedge clock)begin
  sign_node_ff0 <= (dataa[31] ^ datab[31]);
  wire_exp_add_adder_result <= {1'b0, dataa[30:23]} + {1'b0, datab[30:23]};
  dataa_exp_all_one_ff_p1 <= dataa_exp_all_one;
  dataa_exp_not_zero_ff_p1 <= dataa_exp_not_zero;
  dataa_man_not_zero_ff_p1 <= dataa_man_not_zero10;
  dataa_man_not_zero_ff_p2 <= dataa_man_not_zero;
  datab_exp_all_one_ff_p1 <= datab_exp_all_one;
  datab_exp_not_zero_ff_p1 <= datab_exp_not_zero;
  datab_man_not_zero_ff_p1 <= datab_man_not_zero10;
  datab_man_not_zero_ff_p2 <= datab_man_not_zero;
  //wire_man_product2_mult_result.
end

//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


	reg	sign_node_ff1;
	reg	[8:0]	exp_add_p1;
	reg	input_is_infinity_dffe_0;
	reg	input_is_nan_dffe_0;
	reg	input_not_zero_dffe_0;
always @ (*)begin
  sign_node_ff1 <= sign_node_ff0;
  exp_add_p1 <= wire_exp_add_adder_result;
  input_is_infinity_dffe_0 <= (
    (dataa_exp_all_one_ff_p1 & (~ (dataa_man_not_zero_ff_p1 | dataa_man_not_zero_ff_p2)))
    | (datab_exp_all_one_ff_p1 & (~ (datab_man_not_zero_ff_p1 | datab_man_not_zero_ff_p2)))
  );
  input_is_nan_dffe_0 <= (
    (dataa_exp_all_one_ff_p1 & (dataa_man_not_zero_ff_p1 | dataa_man_not_zero_ff_p2)) 
    | (datab_exp_all_one_ff_p1 & (datab_man_not_zero_ff_p1 | datab_man_not_zero_ff_p2))
  );
  input_not_zero_dffe_0 <= (dataa_exp_not_zero_ff_p1 & datab_exp_not_zero_ff_p1);
  //wire_man_product2_mult_result
end
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	wire  [9:0]  bias = {{3{1'b0}}, {7{1'b1}}};
	wire  [9:0]   wire_exp_bias_subtr_result = {1'b0, exp_add_p1[8:0]} - {bias[9:0]};
	wire  [24:0]  man_shift_full = wire_man_product2_mult_result[47] ? wire_man_product2_mult_result[47:23] : wire_man_product2_mult_result[46:22];
	wire sticky_bit = (wire_man_product2_mult_result[47] & wire_man_product2_mult_result[22]) | (|wire_man_product2_mult_result[21:0]);
	wire  lsb_bit = man_shift_full[1];
	wire  round_bit = man_shift_full[0];

	reg	sign_node_ff2;
	reg	input_is_infinity_dffe_1;
	reg	input_is_nan_dffe_1;
	reg	input_not_zero_dffe_1;
	reg	[9:0]	delay_exp_bias;
	reg	delay_man_product_msb_p0;
	reg	[23:0]	man_round_p;
	reg	sticky_dffe;
	reg	lsb_dffe;
	reg	round_dffe;
always @ (posedge clock)begin
  sign_node_ff2 <= sign_node_ff1;
  input_is_infinity_dffe_1 <= input_is_infinity_dffe_0;
  input_is_nan_dffe_1 <= input_is_nan_dffe_0;
  input_not_zero_dffe_1 <= input_not_zero_dffe_0;
  delay_exp_bias <= wire_exp_bias_subtr_result;
  delay_man_product_msb_p0 <= wire_man_product2_mult_result[47];
  man_round_p <= man_shift_full[24:1];
  sticky_dffe <= sticky_bit;
  lsb_dffe <= lsb_bit;
  round_dffe <= round_bit;
end
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	wire  round_carry = (round_dffe & (lsb_dffe | sticky_dffe));
	wire  [24:0] wire_man_round_adder_result = {1'b0, man_round_p} + {{24{1'b0}}, round_carry};


	reg	sign_node_ff3;
	reg	input_is_infinity_ff1;
	reg	input_is_nan_ff1;
	reg	input_not_zero_ff1;
	reg	[9:0]	delay_exp2_bias;
	reg	delay_man_product_msb;
	reg	[24:0]	man_round_p2;
always @ (*)begin
  sign_node_ff3 <= sign_node_ff2;
  input_is_infinity_ff1 <= input_is_infinity_dffe_1;
  input_is_nan_ff1 <= input_is_nan_dffe_1;
  input_not_zero_ff1 <= input_not_zero_dffe_1;
  delay_exp2_bias <= delay_exp_bias;
  delay_man_product_msb <= delay_man_product_msb_p0;
  man_round_p2 <= wire_man_round_adder_result;
end
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	wire  [7:0]  inf_num = {8{1'b1}};

	wire  [9:0] wire_exp_adj_adder_result = delay_exp2_bias + expmod;
	wire  [23:0]  man_result_round = man_round_p2[24] ? man_round_p2[24:1] : man_round_p2[23:0];
	wire  [9:0] expmod = {{8{1'b0}}, (delay_man_product_msb & man_round_p2[24]), (delay_man_product_msb ^ man_round_p2[24])};
	wire  exp_is_zero = (wire_exp_adj_adder_result[9] | (~ result_exp_not_zero));
	wire  result_exp_all_one = &wire_exp_adj_adder_result[7:0];
	wire  exp_is_inf = wire_exp_adj_adder_result[8] ? (~ wire_exp_adj_adder_result[9]) : result_exp_all_one;
	wire  result_exp_not_zero = |wire_exp_adj_adder_result[8:0];

	reg	[7:0]	exp_result_ff;
	reg	[22:0]	man_result_ff;
	reg	sign_node_ff4;
always @ (*)begin
  sign_node_ff4 <= sign_node_ff3;
  exp_result_ff <= (
    (inf_num & {8{((exp_is_inf | input_is_infinity_ff1) | input_is_nan_ff1)}}) 
    | ((wire_exp_adj_adder_result[7:0] & {8{(~ exp_is_zero)}}) & {8{input_not_zero_ff1}})
  );
  man_result_ff <= {
    (
      (
        man_result_round[22] 
        & input_not_zero_ff1
        & (~ input_is_infinity_ff1)
        & (~ exp_is_inf)
        & (~ exp_is_zero)
      ) 
      | (input_is_infinity_ff1 & (~ input_not_zero_ff1))
      | input_is_nan_ff1
    ), 
    (
      man_result_round[21:0] 
      & {22{input_not_zero_ff1}}
      & {22{(~ input_is_infinity_ff1)}}
      & {22{(~ exp_is_inf)}}
      & {22{(~ exp_is_zero)}}
      & {22{(~ input_is_nan_ff1)}}
    )
  };
end

//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	assign result = {sign_node_ff4, exp_result_ff[7:0], man_result_ff[22:0]};
endmodule
